#ifndef _VIEW_H_
#define _VIEW_H_

#include "Vec3D.h"
#include "Matrix.h"
#include "BBox3D.h"

//#include <iostream>



namespace FemViewer {
class BBox3D;
class Tile;
class ViewManager;
class Camera;


class View
{
	friend class Camera;
public:
	/* Default constructor */
	View ();
	/* Copy Constructor */
	View (const View&   pView);
	
	View (const Vec3D&     pCenter);

	View (const Vec3D&     pCenter,
		  const Vec3D&     pDirection);

	View (const Vec3D&     pCenter,
          const Vec3D&     pDirection,
          const Vec3D&     pUp,
          const float      pDistance,
	      const float      pFOVDegrees,
		  const bool	   pOtrhoOn);

	View (const BBox3D& pBBox3D, 
		  const bool	pOrtho);

	View (const BBox3D& pBBox3D, View& pReferenceView);

	View (const BBox3D& pBBox3D,
	      const Vec3D&  pDirection,
	      const Vec3D&  pUp,
		  const bool    pOrtho);
	/* Destructor */
	~View();

	void     drawCenter () const;

	void     dump       (ViewManager&  pViewManager) const;

	void     dump       (std::ostream& pOstream) const;

	Vec3D    getPosition() const;

	void  	initCamera (const Tile&   pTile) /*const*/;

	 	  Matrix<float>& getCameraMatrix()       { return w2c; }
	const Matrix<float>& getCameraMatrix() const { return w2c; }

	View&    operator=  (const View&   pView);

	void     rotate     (const float   pDeltaX,
                       const float   pDeltaY);

	void     scaleFOV   (const float   pFOVFactor);

	void     setCenter   (const Vec3D& pCenter);

	void     translate  (const float   pDeltaX,
		                   const float   pDeltaY);

	const    Vec3D& getDirection() const;

	float	 GetRadious() const;
	float    getDistance() const;

	float    getNearClipDistance() const;
	float    getFarClipDistance () const;

	void TogglePerspective();
private:
	/* Static and const camera params */
	static const Vec3D	vDefaultCenter;
	static const Vec3D	vDefaultDirection;
	static const float  fDeafultRadious;
	static const float  fDefaultDistance;
	static const float  fDefaultFOVDegrees;
	static const Vec3D	vDefaultUp;
	static const float  fInitialObjectDistanceFactor;
	static const float  fMaxFOVDegrees;
	static const float  fMinFOVDegrees;
	static const float	Identity[4][3];
	static const bool   bOrthoState;

  void     ajust(const BBox3D&  pBBox3D);

  void     init (const Vec3D&     pCenter     = vDefaultCenter,
                 const Vec3D&     pDirection  = vDefaultDirection,
                 const Vec3D&     pUp         = vDefaultUp,
                 const float      pDistance   = fDefaultDistance,
                 const float      pFOVDegrees = fDefaultFOVDegrees,
				 const bool		  pOrthoOn    = bOrthoState);


#ifdef FV_CHECK_INVARIANTS
  void invariants() const;
#endif // #ifdef GLV_BEBUG
  Matrix<float> w2c;
  Vec3D vCenter;
  Vec3D vDirection;
  float fRadious;
  float fDistance;
  float fFOVDegrees;
  float fBBoxRadious;
  Vec3D vUp;

public:
  bool bOrthoOn;

};

} // end namespace FemViewer

#endif /* _VIEW_H_
*/
